--==============================--
--desc: 获取表的所有key值
--time:2018-01-24 02:41:07
--==============================--
function table.keys(tbl)
	local keys = {}
	for k, _ in pairs(tbl) do
		table.insert(keys, k)
	end
	return keys
end

--==============================--
--desc: 获取表的所有value值
--time:2018-01-24 02:41:07
--==============================--
function table.values(tbl)
	local values = {}
	for _, v in pairs(tbl) do
		table.insert(values, v)
	end
	return values
end

--==============================--
--desc: 获取表的数量
--time:2018-01-24 02:42:58
--==============================--
function table.count(tbl)
	local c = 0
	for _, _ in pairs(tbl) do
		c = c + 1
	end
	return c
end

--==============================--
--desc: 数组拆分
--time:2018-01-24 02:39:19
--==============================--
function table.sub(tbl, offset, size)
	local tsize = #tbl
	size = math.min(tsize - offset + 1, size)
	-- print(offset, size, tsize)
	-- table loop
	local t = {}
	for i = 1, size, 1 do
		t[i] = tbl[offset + i - 1]
	end
	return t
end

--==============================--
--desc: 创建只读表
--time:2018-01-24 02:39:25
--==============================--
function table.read_only(t)
	local temp = t or {}
	local mt = {
		__index = function(t, k)
			return temp[k]
		end,
		__newindex = function(t, k, v)
			error("attempt to update a read-only table! key=" .. k .. ".")
		end
	}
	setmetatable(temp, mt)
	return temp
end

-- 基础显示
local function base_tostring(v)
	if not v or type(v) == "number" then
		return tostring(v)
	end
	return "'" .. tostring(v) .. "'"
end

-- 表内容
local function table_tostring(t, conf, level)
	if type(t) ~= "table" then
		return base_tostring(t)
	end
	-- set in cache
	level = level or 1
	conf = conf or {}
	conf.cache = conf.cache or {}
	if conf.cache[t] ~= nil then
		return base_tostring(t) -- no loop call
	end
	conf.cache[t] = 1

	-- array tostring
	if table.isarray(t) then
		local str = "["
		local index = 0
		for k, v in ipairs(t) do
			-- filter
			if not (conf.filter and not conf.filter(t, k, v)) then
				-- check index
				index = index + 1
				if index > 1 then
					str = str .. ","
				end
				-- check level
				local max_level = tonumber(conf.level) or 0
				local c_str = ""
				if max_level > 0 and level >= max_level then
					c_str = base_tostring(v)
				else
					c_str = table_tostring(v, conf, level + 1)
				end
				-- tostring
				str = str .. c_str
			end
		end
		str = str .. "]"
		return str
	end

	-- to string
	local str = "{"
	local index = 0
	for k, v in pairs(t) do
		-- filter
		if not (conf.filter and not conf.filter(t, k, v)) then
			-- check index
			index = index + 1
			if index > 1 then
				str = str .. ","
			end
			-- check level
			local max_level = tonumber(conf.level) or 0
			local c_str = ""
			if max_level > 0 and level >= max_level then
				c_str = base_tostring(v)
			else
				c_str = table_tostring(v, conf, level + 1)
			end
			-- tostring
			str = str .. "'" .. tostring(k) .. "':" .. c_str .. ""
		end
	end
	str = str .. "}"
	return str
end

--==============================--
--desc: 表转成简易的json样式 table to string
--time:2018-01-24 02:39:40
--==============================--
function table.tostring(t, level)
	return table_tostring(
		t,
		{
			level = level,
			cache = {},
			filter = function(t, k, v)
				-- filter type
				if type(v) == "function" or type(v) == "userdate" then
					return false
				end
				-- filter _value
				-- if k:find("_") == 0 then
				-- 	return false
				-- end
				return true
			end
		},
		1
	)
end

--==============================--
--desc: 显示表的所有信息
--time:2018-01-24 02:40:00
--==============================--
function table.toinfo(t)
	return table_tostring(t)
end

--==============================--
--desc: 获取表的所有key值
--time:2018-01-24 02:41:07
--==============================--
function isArrayTable(t)
	if type(t) ~= "table" then
		return false
	end

	local n = #t
	for i, v in pairs(t) do
		if type(i) ~= "number" then
			return false
		end

		if i > n then
			return false
		end
	end

	return true
end
--==============================--
--desc: 判断表是否是数组
--time:2018-11-04
--==============================--
function table.isarray(t)
	if type(t) ~= "table" then
		return false
	end
	local n = #t
	for i, v in pairs(t) do
		if type(i) ~= "number" then
			return false
		end
		if i > n then
			return false
		end
	end
	return true
end
-- -- test
-- local a = {a = 1, b = 2, c = 3}
-- local b = {t = a, e = 3}
-- print(table.tostring(b, 1))
-- print(table.toinfo(b))
